﻿using NPOI.SS.UserModel;
using NPOI.SS.Util;
using System.Data;

namespace tools.office.npoi
{
    /// <summary>
    /// 创建表格帮助类
    /// </summary>
    public static class CreateTableHelper
    {
        /// <summary>
        /// 创建一行标题行
        /// </summary>
        /// <param name="sheet">工作表实例</param>
        /// <param name="startRow">开始行信息</param>
        /// <param name="titleColumnConfigs">标题列配置集合</param>
        /// <param name="defaultStyle">默认单元格样式</param>
        /// <param name="coloredStyle">彩色单元格样式</param>
        /// <returns>标题结束列的下一列的索引</returns>
        public static int CreateTitleRowWithOneRow(
            ISheet sheet,
            RowInfo startRow,
            List<OneRowTitleColumnInfo> titleColumnConfigs,
            ICellStyle defaultStyle,
            ICellStyle coloredStyle)
        {
            IRow row = sheet.CreateRow(startRow.Index);
            row.HeightInPoints = startRow.Height;

            int colIndex = 0;

            foreach (var titleColumnConfig in titleColumnConfigs)
            {
                ICellStyle cellStyle = titleColumnConfig.IsColored ? coloredStyle : defaultStyle;

                ICell cell = row.CreateCell(colIndex);
                cell.SetCellValue(titleColumnConfig.Title);
                cell.CellStyle = cellStyle;

                sheet.SetColumnWidth(colIndex, titleColumnConfig.Width * 256);

                colIndex++;
            }

            return colIndex;
        }

        /// <summary>
        /// 创建两行标题行
        /// </summary>
        /// <param name="sheet">工作表实例</param>
        /// <param name="startRow">开始行信息</param>
        /// <param name="endRow">结束行信息</param>
        /// <param name="titleColumnConfigs">标题列配置集合</param>
        /// <param name="defaultStyle">默认单元格样式</param>
        /// <param name="coloredStyle">彩色单元格样式</param>
        /// <returns>标题结束列的下一列的索引</returns>
        public static int CreateTitleRowWithTwoRow(
            ISheet sheet,
            RowInfo startRow,
            RowInfo endRow,
            List<TwoRowTitleColumnInfo> titleColumnConfigs,
            ICellStyle defaultStyle,
            ICellStyle coloredStyle)
        {
            IRow row1 = sheet.CreateRow(startRow.Index);
            row1.HeightInPoints = startRow.Height;

            IRow row2 = sheet.CreateRow(endRow.Index);
            row2.HeightInPoints = endRow.Height;

            int colIndex = 0;

            foreach (var titleColumnConfig in titleColumnConfigs)
            {
                ICellStyle cellStyle = titleColumnConfig.IsColored ? coloredStyle : defaultStyle;

                // 两行标题只有两种情况：行合并/列合并
                if (titleColumnConfig.RowSpan > 1)
                {
                    CellRangeAddress rowMerge = new(startRow.Index, endRow.Index, colIndex, colIndex);
                    sheet.AddMergedRegion(rowMerge);

                    ICell cell1 = row1.CreateCell(colIndex);
                    cell1.SetCellValue(titleColumnConfig.Title); // 主标题设置在第一个单元格
                    cell1.CellStyle = cellStyle;

                    ICell cell2 = row2.CreateCell(colIndex);
                    cell2.CellStyle = cellStyle;

                    sheet.SetColumnWidth(colIndex, titleColumnConfig.Width * 256);
                }
                else
                {
                    //        主标题
                    // 副标题1 副标题2 副标题3

                    CellRangeAddress colMerge = new(
                        startRow.Index, startRow.Index, colIndex, colIndex + titleColumnConfig.ColSpan - 1);

                    sheet.AddMergedRegion(colMerge);

                    // 创建第一行主标题
                    ICell mainCell = row1.CreateCell(colIndex);
                    mainCell.SetCellValue(titleColumnConfig.Title);
                    mainCell.CellStyle = cellStyle;

                    // 为第一行其他单元格设置样式（处理边框丢失问题）
                    for (int i = 1; i < titleColumnConfig.ColSpan; i++)
                    {
                        ICell emptyCell = row1.CreateCell(colIndex + i);
                        emptyCell.CellStyle = cellStyle;
                    }

                    if (titleColumnConfig.SubTitles == null) continue;
                    if (titleColumnConfig.SubTitles.Count != titleColumnConfig.ColSpan)
                    {
                        throw new ArgumentException("副标题数量必须与列跨度一致");
                    }

                    // 创建第二行副标题
                    for (int i = 0; i < titleColumnConfig.SubTitles.Count; i++)
                    {
                        ColInfo colInfo = titleColumnConfig.SubTitles.ElementAt(i);

                        ICell subCell = row2.CreateCell(colIndex + i);
                        subCell.SetCellValue(colInfo.Title);
                        subCell.CellStyle = cellStyle;

                        sheet.SetColumnWidth(colIndex + i, colInfo.Width * 256);
                    }
                }

                colIndex += titleColumnConfig.ColSpan;
            }

            return colIndex;
        }

        /// <summary>
        /// 创建数据行
        /// </summary>
        /// <param name="sheet">工作表实例</param>
        /// <param name="startRow">数据行起始信息</param>
        /// <param name="dataTable">数据</param>
        /// <param name="dataColumnConfigs">数据列配置集合</param>
        /// <param name="defaultStyle">默认单元格样式</param>
        /// <param name="coloredStyle">彩色单元格样式</param>
        /// <returns>数据结束行的下一行的索引</returns>
        public static int CreateDataRow(
            ISheet sheet,
            RowInfo startRow,
            DataTable dataTable,
            List<DataColumnInfo> dataColumnConfigs,
            ICellStyle defaultStyle,
            ICellStyle coloredStyle)
        {
            for (int i = 0; i < dataTable.Rows.Count; i++)
            {
                DataRow dataRow = dataTable.Rows[i];

                int rowIndex = startRow.Index + i;
                int colIndex = 0;

                IRow row = sheet.CreateRow(rowIndex);
                row.HeightInPoints = startRow.Height;

                foreach (var dataColumnConfig in dataColumnConfigs)
                {
                    ICellStyle cellStyle = dataColumnConfig.IsColored ? coloredStyle : defaultStyle;

                    ICell cell = row.CreateCell(colIndex);
                    cell.CellStyle = cellStyle;

                    if (!string.IsNullOrEmpty(dataColumnConfig.FieldName) 
                        && dataRow.Table.Columns.Contains(dataColumnConfig.FieldName))
                    {
                        SetCellValue(cell, dataRow[dataColumnConfig.FieldName]);
                    }

                    if (dataColumnConfig.ColSpan > 1)
                    {
                        // 合并列
                        CellRangeAddress merge = new(
                            rowIndex, rowIndex, colIndex, colIndex + dataColumnConfig.ColSpan - 1);

                        sheet.AddMergedRegion(merge);

                        // 为合并区域的其他单元格设置样式（处理边框丢失问题）
                        for (int j = 1; j < dataColumnConfig.ColSpan; j++)
                        {
                            ICell emptyCell = row.CreateCell(colIndex + j);
                            emptyCell.CellStyle = cellStyle;
                        }

                        colIndex += dataColumnConfig.ColSpan;
                    }
                    else
                    {
                        colIndex++;
                    }
                }
            }

            return startRow.Index + dataTable.Rows.Count;
        }

        /// <summary>
        /// 设置单元格的值
        /// </summary>
        /// <param name="cell">单元格实例</param>
        /// <param name="value">要设置的值</param>
        public static void SetCellValue(ICell cell, object? value)
        {
            if (value != null && value != DBNull.Value)
            {
                switch (value)
                {
                    case string stringValue:
                        cell.SetCellValue(stringValue);
                        break;

                    case DateTime dateTimeValue:
                        cell.SetCellValue(dateTimeValue);
                        break;

                    case bool boolValue:
                        cell.SetCellValue(boolValue);
                        break;

                    default:
                        cell.SetCellValue(Convert.ToDouble(value));
                        break;
                }
            }
        }
    }
}
